﻿using System;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using Relocation.Data;
using System.Data.Objects;
using System.Threading;
using Relocation.Base;
using Relocation.Com;
using Relocation.Base.UI;


namespace Relocation.Controls
{
	/// <summary>
	/// 快速搜索用户控件
	/// </summary>
	public partial class MainTreeView : BaseControl
	{
		/// <summary>
		/// 正在刷新
		/// </summary>
		public bool IsRefreshing
		{
			get;
			private set;
		}


		private RelocateWindow RelocateWindow;


		public MainTreeView()
			: base()
		{
			Initialize();
		}

		public MainTreeView(Session session)
			: base(session)
		{
			Initialize();
		}

		public void init()
		{
			this.Session.DataRefresh = true;
		}


		private void Initialize()
		{
			InitializeComponent();
		}

		#region 树形导航刷新

		/// <summary>
		/// 调后台线程刷新整个树.
		/// </summary>
		public override void Refresh()
		{
			GC.Collect();
			base.Refresh();
			if (!Session.DataRefresh || this.IsRefreshing)
				return;
			if (this.RelocateWindow != null)
			{
				this.RelocateWindow.Close();
				if (!this.RelocateWindow.IsDisposed)
				{
					this.Session.DataRefresh = false;
					return;
				}
			}
			this.treeView.Nodes.Clear();
			WaitForm wait = new WaitForm("加载数据", "正在加载数据，请稍候...");
			ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object o) {
				this.IsRefreshing = true;
				TreeNode node = CreateTreeNode(Session.Project);
				this.ExecInvoke(new MethodInvoker(delegate() {
					wait.Close();
					this.treeView.Nodes.Add(node);
					this.toolStripSearchString.Focus();
					if (Session.User.role != "general")
						this.treeView.ContextMenuStrip = this.contextMenuTree;
					else
						this.treeView.ContextMenuStrip = null;
					Session.DataRefresh = false;

				}));
				this.IsRefreshing = false;
			}));
			wait.ShowDialog();

		}

		/// <summary>
		/// 刷新树中被修改的节点.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="entity">The entity.</param>
		public void Refresh<TEntity>(TEntity entity, EntityState entityState)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			switch (entity.GetType().Name)
			{
				case "Relocatees":
					Refresh(entity as Relocatees, entityState);
					break;
				case "Projects":
					Refresh(entity as Projects, entityState);
					break;
			}
		}

		/// <summary>
		/// 刷新树中被修改的项目.
		/// </summary>
		/// <param name="entity">The entity.</param>
		private void Refresh(Projects entity, EntityState entityState)
		{
			TreeNode entityNode = GetNode(entity);
			if (entityNode == null)
			{
				Log.Error("未找到需要更新的项目！");
				return;
			}
			entityNode.Text = entity.projectName;
			entityNode.Tag = entity;
			entityNode.ToolTipText = "项目编号:" + entity.projectCode + " | 拆迁许可证号:" + entity.codes;
		}

		// 刷新树中被修改的拆迁户        
		private void Refresh(Relocatees entity, EntityState entityState)
		{
			TreeNode entityNode = GetNode(entity);
			switch (entityState)
			{
				case EntityState.Deleted:
					entityNode.Remove();
					break;
				case EntityState.Modified:
					if (entityNode == null)
					{
						Log.Error("未找到需要更新的拆迁户!");
						return;
					}
					InitRelocateesNode(entityNode, entity);
					showNode(entityNode);
					break;
				case EntityState.Detached:
				case EntityState.Added:

					TreeNode node = new TreeNode();
					InitRelocateesNode(node, entity);
					this.treeView.Nodes[0].Nodes.Add(node);
					showNode(node);
					break;
			}

		}

		#endregion

		#region 查找树形节点

		/// <summary>
		/// 根据实体对象查找在树形中的节点.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="entity">The entity.</param>
		public TreeNode GetNode<TEntity>(TEntity entity)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			switch (entity.GetType().Name)
			{
				case "Relocatees":
					return GetNode(entity as Relocatees);
				case "Projects":
					return GetNode(entity as Projects);
			}
			return null;
		}

		/// <summary>
		/// 根据项目实体对象查找在树形中的节点.
		/// </summary>
		/// <param name="entity">The entity.</param>
		/// <returns></returns>
		private TreeNode GetNode(Projects entity)
		{
			foreach (TreeNode node1 in this.treeView.Nodes)
				if (((Projects)node1.Tag).projectID == entity.projectID)
					return node1;
			return null;
		}

		/// <summary>
		/// 根据拆迁户实体对象查找在树形中的节点.
		/// </summary>
		/// <param name="entity">The entity.</param>
		/// <returns></returns>
		private TreeNode GetNode(Relocatees entity)
		{
			foreach (TreeNode node1 in this.treeView.Nodes)
			{
				foreach (TreeNode node2 in node1.Nodes)
				{
					if (((Relocatees)node2.Tag).relocateID == entity.relocateID)
						return node2;
				}
			}
			return null;
		}
		#endregion

		#region 加载树形数据

		/// <summary>
		/// 加载项目数据.
		/// </summary>
		/// <param name="project_id">The projectID.</param>
		private TreeNode CreateTreeNode(Projects project)
		{
			TreeNode node = new TreeNode();
			node = InitProjectNode(project, node);
			node.Nodes.AddRange(this.GetRelocateNodes(project));
			return node;
		}

		/// <summary>
		/// 加载拆迁户数据.
		/// </summary>		
		private TreeNode[] GetRelocateNodes(Projects project)
		{
			ObjectQuery<Relocatees> relocatees = project.Relocatees.CreateSourceQuery();
			int count = relocatees.Count();
			TreeNode[] nodes = new TreeNode[count];
			TreeNode node;
			int index = 0;
			foreach (Relocatees relocate in relocatees)
			{
				node = new TreeNode();
				InitRelocateesNode(node, relocate);
				nodes[index++] = node;
			}
			return nodes;
		}

		#endregion

		#region 通过对象创建TreeNode

		/// <summary>
		/// 初始化Relocatees对应的TreeNode
		/// </summary>		
		private TreeNode InitRelocateesNode(TreeNode node, Relocatees relocatees)
		{
			node.Text = relocatees.head;
			node.Tag = relocatees;
			string strStatus;
			if (relocatees.statusFlag != null)
			{
				if (Convert.ToInt32(relocatees.statusFlag) == 0)
					strStatus = " | 未安置";
				else if (Convert.ToInt32(relocatees.statusFlag) == 1)
					strStatus = " | 已安置";
				else
					strStatus = " | 无需安置";

				node.ToolTipText = "拆迁证号：" + relocatees.codes + " | 人口数:" + relocatees.persons + " | 拆迁面积:" + relocatees.area + "平方米" + strStatus;
				setRelocatImageKey(node, Convert.ToInt32(relocatees.statusFlag));//安置状态
			}

			if (Session.User.role != "general")
				node.ContextMenuStrip = this.contextMenuRelocation;
			return node;
		}

		/// <summary>
		/// 创建Projects对应的TreeNode
		/// </summary>		
		private TreeNode InitProjectNode(Projects project, TreeNode node)
		{
			node.Text = project.projectName;
			node.Tag = project;
			node.ImageKey = "ProjectWindow";
			node.ToolTipText = "项目编号:" + project.projectCode + " | 拆迁许可证号:" + project.codes;
			if (Session.User.role != "general")
				node.ContextMenuStrip = this.contextMenuProject;
			return node;
		}

		#endregion

		// 显示、并选中节点
		private void showNode(TreeNode node)
		{
			node.EnsureVisible();
			this.treeView.SelectedNode = null;
			this.treeView.SelectedNode = node;
		}

		#region 事件相关方法

		/// <summary>
		/// Handles the Click event of the buttonSearch control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void buttonSearch_Click(object sender, EventArgs e)
		{
			this.toolStripSearchString.Text = this.toolStripSearchString.Text.Trim();
			if (this.toolStripSearchString.Text == "")
				return;
			TreeNode node = searchNode(this.treeView.Nodes, this.toolStripSearchString.Text);
			if (node != null)
			{
				this.treeView.Focus();
				showNode(node);
			} else
				MyMessagebox.Show("未找到符合要求的数据！");
		}

		private void toolStripFindNext_Click(object sender, EventArgs e)
		{
			this.toolStripSearchString.Text = this.toolStripSearchString.Text.Trim();
			if (this.toolStripSearchString.Text == "")
				return;
			TreeNode node = (this.treeView.SelectedNode == null) ? searchNode(this.treeView.Nodes, this.toolStripSearchString.Text)
				: searchNextNode(this.treeView.SelectedNode, this.toolStripSearchString.Text);
			if (node != null)
			{
				this.treeView.Focus();
				showNode(node);
			} else
				MyMessagebox.Show("未找到符合要求的数据！");
		}

		/// <summary>
		/// Searches the node.
		/// </summary>
		/// <param name="nodes">The nodes.</param>
		/// <param name="searchString">The search string.</param>
		/// <returns></returns>
		private TreeNode searchNode(TreeNodeCollection nodes, string searchString)
		{
			if (nodes.Count == 0)
				return null;
			foreach (TreeNode node in nodes)
			{
				if (node.Level > 0 && node.Text.Contains(searchString))
				{
					return node;
				} else
				{
					TreeNode childNode = searchNode(node.Nodes, searchString);
					if (childNode != null)
						return childNode;
				}
			}
			return null;
		}

		/// <summary>
		/// Searches the next node.
		/// </summary>
		/// <param name="node">The node.</param>
		/// <param name="searchString">The search string.</param>
		/// <returns></returns>
		private TreeNode searchNextNode(TreeNode currentNode, string searchString)
		{
			TreeNode node = searchNode(currentNode.Nodes, searchString);
			if (node != null)
				return node;
			TreeNode nextNode = currentNode.NextNode;
			if (nextNode == null)
			{
				TreeNode pnode = currentNode.Parent;
				while (pnode != null && pnode.NextNode == null)
					pnode = pnode.Parent;
				if (pnode == null)
					return null;
				if (pnode.NextNode.Text.Contains(searchString))
					return pnode.NextNode;
				return searchNextNode(pnode.NextNode, searchString);
			} else if (nextNode.Text.Contains(searchString))
				return nextNode;
			else
				return searchNextNode(nextNode, searchString);
		}

		/// <summary>
		/// Shows the form.
		/// </summary>
		/// <param name="form">The form.</param>
		private void showForm(Form form)
		{
			try
			{
				foreach (Form oldForm in this.splitContainer.Panel2.Controls)
				{
					oldForm.Close();
				}
				form.FormBorderStyle = FormBorderStyle.None;
				form.Dock = DockStyle.Fill;
				form.TopLevel = false;
				form.Parent = this.splitContainer.Panel2;
				form.Show();
			} catch (Exception ex)
			{	
				Log.Error(ex.GetInnerExceptionMessage());
				System.Diagnostics.Debug.WriteLine(ex);
				throw;
			}

		}

		/// <summary>
		/// Handles the AfterSelect event of the treeView control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.Windows.Forms.TreeViewEventArgs"/> instance containing the event data.</param>
		private void treeView_AfterSelect(object sender, TreeViewEventArgs e)
		{
			try
			{
				TreeNode currentNode = this.treeView.SelectedNode;

				if (currentNode.Level == 1)
				{
					Relocatees relocatees = (Relocatees)currentNode.Tag;
					if (relocatees != null)
					{
						if (this.RelocateWindow == null || this.RelocateWindow.IsDisposed)
						{
							this.RelocateWindow = new RelocateWindow(Session);
							showForm(this.RelocateWindow);
						}
						this.RelocateWindow.LoadRelocate(relocatees);
						this.RelocateWindow.EndEdit();
					}
				}
			} catch (Exception ex)
			{
				Log.Error(ex.GetInnerExceptionMessage());
				System.Diagnostics.Debug.WriteLine(ex);
				MyMessagebox.Show("操作失败！");
			}

		}

		/// <summary>
		/// Handles the Click event of the buttonExpandAll control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void buttonExpandAll_Click(object sender, EventArgs e)
		{
			this.treeView.ExpandAll();
		}

		/// <summary>
		/// Handles the Click event of the buttonCollapseAll control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void buttonCollapseAll_Click(object sender, EventArgs e)
		{
			this.treeView.CollapseAll();
		}

		/// <summary>
		/// Handles the Click event of the buttonRefresh control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void buttonRefresh_Click(object sender, EventArgs e)
		{
			try
			{
				if (this.IsRefreshing)
				{
					MyMessagebox.Show("菜单正在刷新，请稍候...");
					return;
				}
				this.Session.DataRefresh = true;
				this.Refresh();
			} catch (Exception ex)
			{	
				Log.Error(ex.GetInnerExceptionMessage());
				System.Diagnostics.Debug.WriteLine(ex);
				MyMessagebox.Show("操作失败！");
			}
		}

		/// <summary>
		/// Handles the KeyPress event of the textSearchString control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.Windows.Forms.KeyPressEventArgs"/> instance containing the event data.</param>
		private void textSearchString_KeyPress(object sender, KeyPressEventArgs e)
		{
			if (e.KeyChar == '\r')
				buttonSearch_Click(sender, e);
		}

		/// <summary>
		/// Handles the Enter event of the MainTreeView control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void MainTreeView_Enter(object sender, EventArgs e)
		{
			this.toolStripSearchString.Focus();
		}

		// 新增拆迁户
		private void toolStripRelocation_Click(object sender, EventArgs e)
		{
			try
			{
				using (RelocateWindow relocateWindow = new RelocateWindow(Session))
				{
					relocateWindow.Text = "拆迁户登记";
					relocateWindow.MaximumSize = new System.Drawing.Size(658, 660);
					relocateWindow.MinimumSize = new System.Drawing.Size(658, 660);
					relocateWindow.ShowDialog();
				}
			} catch (Exception ex)
			{	
				Log.Error(ex.GetInnerExceptionMessage());
				System.Diagnostics.Debug.WriteLine(ex);
				MyMessagebox.Show("操作失败！");
			}
		}

		// 新增拆迁户
		private void menuItemAddRelocation_Click(object sender, EventArgs e)
		{
			try
			{
				TreeNode selectedNode = (TreeNode)((ToolStripMenuItem)sender).Owner.Tag;
				RelocateWindow relocateWindow = new RelocateWindow(Session);
				using (relocateWindow)
				{
					relocateWindow.Text = "拆迁户登记";
					relocateWindow.MaximumSize = new System.Drawing.Size(658, 660);
					relocateWindow.MinimumSize = new System.Drawing.Size(658, 660);
					relocateWindow.ShowDialog();
				}
			} catch (Exception ex)
			{	
				Log.Error(ex.GetInnerExceptionMessage());
				System.Diagnostics.Debug.WriteLine(ex);
				MyMessagebox.Show("操作失败！");
			}
		}

		// 修改拆迁户
		private void menuItemEditRelocatees_Click(object sender, EventArgs e)
		{
			try
			{
				if (this.RelocateWindow != null && !this.RelocateWindow.IsDisposed)
				{
					this.RelocateWindow.BeginEdit();
				}
			} catch (Exception ex)
			{	
				Log.Error(ex.GetInnerExceptionMessage());
				System.Diagnostics.Debug.WriteLine(ex);
				MyMessagebox.Show("操作失败！");
			}
		}

		/// <summary>
		/// Handles the NodeMouseClick event of the treeView control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.Windows.Forms.TreeNodeMouseClickEventArgs"/> instance containing the event data.</param>
		private void treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			//if (e.Node.ContextMenuStrip != null)
			//        e.Node.ContextMenuStrip.Tag = e.Node;
			//this.treeView.SelectedNode = e.Node;
		}

		// 删除拆迁户
		private void menuItemDelRelocatees_Click(object sender, EventArgs e)
		{
			deleteRelocatees((TreeNode)((ToolStripMenuItem)sender).Owner.Tag);
		}

		public void deleteRelocatees(TreeNode relocateesNode)
		{
			if (relocateesNode != null && MyMessagebox.Confirm("您确定要删除此拆迁户的信息吗？").IsYes())
			{
				try
				{
					this.Session.DataModel.Connection.Open();
				} catch (Exception ex)
				{
					Log.Error(ex.Message);
					MyMessagebox.Show("数据库繁忙，请稍候再试！");
					return;
				}

				System.Data.Common.DbTransaction transaction = this.Session.DataModel.Connection.BeginTransaction();
				try
				{
					Relocatees relocatees = (Relocatees)relocateesNode.Tag;
					string strPath = relocatees.fileName == null ? string.Empty : relocatees.fileName.Trim();
					this.Session.DataModel.Delete(relocatees);
					Relocation.Com.Tools.Tools.DeleteFile_Directory(strPath);
					transaction.Commit();
					this.RelocateWindow.Close();
					this.RelocateWindow = null;
					RemoveNodeShowNextNode(relocateesNode);
				} catch (Exception ex)
				{
					Log.Error(ex.Message);
					transaction.Rollback();
					MyMessagebox.Error(ex.Message);
					return;
				}
				this.Session.DataModel.Connection.Close();

			}
		}

		/// <summary>
		/// 移除节点，并选中、显示下一个节点（如果没有下一个节点，则选中上一个节点，如果没有上一个节点，则选中上一级节点）
		/// </summary>
		/// <param name="node"></param>
		private void RemoveNodeShowNextNode(TreeNode node)
		{
			try
			{
				if (node != null)
				{
					TreeNode nextNode = node.NextNode != null ? node.NextNode : (node.PrevNode != null ? node.PrevNode : node.Parent);
					node.Remove();
					if (nextNode != null)
						showNode(nextNode);
				}
			} catch (Exception ex)
			{
				Log.Error(ex.GetInnerExceptionMessage());
				System.Diagnostics.Debug.WriteLine(ex);
				throw;
			}

		}

		// 修改项目
		private void MenuItemAlterProject_Click(object sender, EventArgs e)
		{
			try
			{
				TreeNode selectedNode = (TreeNode)((ToolStripMenuItem)sender).Owner.Tag;
				Projects project = (Projects)selectedNode.Tag;
				ProjectWindow projectWindow = new ProjectWindow(Session, project);
				projectWindow.Text = "项目修改";
				if (projectWindow.ShowDialog().IsOK())
				{
					TreeNode projectNode = this.GetNode(project);
					if (projectNode != null)
						this.InitProjectNode(project, projectNode);
				}
			} catch (Exception ex)
			{
				Log.Error(ex.GetInnerExceptionMessage());
				System.Diagnostics.Debug.WriteLine(ex);
				MyMessagebox.Show("操作失败！");
			}
		}

		/// <summary>
		/// Handles the Click event of the menuItemSelectProject control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void menuItemSelectProject_Click(object sender, EventArgs e)
		{
			MainWindow mainWin = (MainWindow)this.FindForm();
			mainWin.projectChoose_Click(sender, e);
		}

		/// <summary>
		/// Handles the Click event of the menuItemVisible control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void menuItemVisible_Click(object sender, EventArgs e)
		{
			this.splitContainer.Panel1Collapsed = true;
			this.splitContainer.ContextMenuStrip = contextMenuNavigate;
		}

		/// <summary>
		/// Handles the Click event of the menuItemNavigate control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void menuItemNavigate_Click(object sender, EventArgs e)
		{
			this.splitContainer.Panel1Collapsed = false;
			this.splitContainer.ContextMenuStrip = null;
		}

		#endregion

		/// <summary>
		/// 根据安置户的安置状态修改背景色和图标
		/// </summary>
		/// <param name="node">节点</param>
		/// <param name="status">状态</param>
		private void setRelocatImageKey(TreeNode node, int status)
		{
			try
			{
				switch (status)
				{
					case 0:
						node.ImageKey = "Relocatees1";
						node.ForeColor = Color.Red;
						break;
					case 1:
						node.ImageKey = "Relocatees2";
						node.ForeColor = Color.Green;
						break;
					default:
						node.ImageKey = "Relocatees";
						node.ForeColor = Color.Black;
						break;
				}

			} catch (Exception e)
			{
				Log.Error(e.Message);
			}
		}

		private void treeView_BeforeSelect(object sender, TreeViewCancelEventArgs e)
		{
			if (this.RelocateWindow != null
				&& this.RelocateWindow.FieldIsChanged
				&& !MyMessagebox.Confirm("数据已更改，确定要放弃更改吗？").IsOK())
				e.Cancel = true;
		}

		private void treeView_MouseClick(object sender, MouseEventArgs e)
		{
			try
			{
				if (e.Button.Equals(MouseButtons.Right))
				{
					TreeNode node = this.treeView.GetNodeAt(e.Location);
					if (node.ContextMenuStrip != null)
						node.ContextMenuStrip.Tag = node;
					this.treeView.SelectedNode = node;
				}
			} catch (Exception ex)
			{
				Log.Error(ex.GetInnerExceptionMessage());
				System.Diagnostics.Debug.WriteLine(ex);
				throw;
			}
		}

	}
}
